//
// Created by Xiaoyun on 2023/3/21.
//
#include "led.h"
#include <stdio.h>
#define max(a, b) ((a>b)?a:b)
#define min(a, b) ((a<b)?a:b)

/**
 * @brief Underlying initialization of the RGB LED
 * @note need user to implement the function
 */
__weak void LED_Init() {

}

/**
 *
 * @brief Set the light of the RGB LED
 * @param R : uint8_t
 * @param G : uint8_t
 * @param B : uint8_t
 * @note need user to implement the function
 */
__weak void LED_Set_RGB(uint8_t R, uint8_t G, uint8_t B) {

}

/**
 *
 * @brief Get the value of the RGB LED
 * @param RGB
 * @note need user to implement the function
 */
__weak void LED_Get_RGB_t(RGB_t* RGB) {

}

/**
 *
 * @brief Set the light of the RGB LED
 * @param RGB : RGB_t
 */
void LED_Set_RGB_t(RGB_t RGB) {
  LED_Set_RGB(RGB.R, RGB.G, RGB.B);
}

/**
 * @brief Converting HSV model to RGB model
 * @param HSV : HSV_t
 * @param RGB : RGB_t*
 */
void HSV_t2RGB_t(HSV_t HSV, RGB_t *RGB) {
  HSV.H = HSV.H % 179;
  if (HSV.S == 0) {
    RGB->R = RGB->G = RGB->B = HSV.V;
  } else {
    float h = HSV.H / 30.0;
    uint8_t i = (int) h;
    float f = h - i;
    uint8_t a = HSV.V * (255.0 - HSV.S) / 255.0;
    uint8_t b = HSV.V * (255.0 - HSV.S * f) / 255.0;
    uint8_t c = HSV.V * (255.0 - HSV.S * (1 - f)) / 255.0;
    switch (i) {
      case 0:
        RGB->R = HSV.V;
        RGB->G = c;
        RGB->B = a;
        break;
      case 1:
        RGB->R = b;
        RGB->G = HSV.V;
        RGB->B = a;
        break;
      case 2:
        RGB->R = a;
        RGB->G = HSV.V;
        RGB->B = c;
        break;
      case 3:
        RGB->R = a;
        RGB->G = b;
        RGB->B = HSV.V;
        break;
      case 4:
        RGB->R = c;
        RGB->G = a;
        RGB->B = HSV.V;
        break;
      default:
        RGB->R = HSV.V;
        RGB->G = a;
        RGB->B = b;
        break;
    }
  }
}

/**
 *
 * @brief Converting RGB model to HSV model
 * @param RGB : RGB_t
 * @param HSV : HSV_t*
 */
void RGB_t2HSV_t(RGB_t RGB, HSV_t *HSV) {
  uint8_t rgb_max = max(max(RGB.R, RGB.G), RGB.B);
  uint8_t rgb_min = min(min(RGB.R, RGB.G), RGB.B);
  HSV->V = rgb_max;
  HSV->S = 255.0 * (rgb_max - rgb_min) / rgb_max;
  int h;
  if (RGB.R == rgb_max)h = (RGB.G - RGB.B) / (rgb_max - rgb_min + 0.0) * 30.0;
  if (RGB.G == rgb_max)h = 60.0 + (RGB.B - RGB.R) / (rgb_max - rgb_min + 0.0) * 30.0;
  if (RGB.B == rgb_max)h = 120.0 + (RGB.R - RGB.G) / (rgb_max - rgb_min + 0.0) * 30.0;
  if (h < 0)h = h + 180.0;
  HSV->H = h;
}

/**
 *
 * @brief Set the LED with H, S, V
 * @param H : uint8_t
 * @param S : uint8_t
 * @param V : uint8_t
 */
void LED_Set_HSV(uint8_t H, uint8_t S, uint8_t V) {
  static RGB_t RGB;
  HSV_t HSV;
  HSV.H = H;
  HSV.S = S;
  HSV.V = V;
  HSV_t2RGB_t(HSV, &RGB);
  LED_Set_RGB_t(RGB);
}

/**
 *
 * @brief Set the LED with HSV_t
 * @param HSV : HSV_t
 */
void LED_Set_HSV_t(HSV_t HSV) {
  RGB_t RGB;
  HSV_t2RGB_t(HSV, &RGB);
  LED_Set_RGB_t(RGB);
}

/**
 *
 * @brief Set HSV_t of LED
 * @param HSV : HSV_t*
 */
void LED_Get_HSV_t(HSV_t* HSV) {
  RGB_t RGB;
  LED_Get_RGB_t(&RGB);
  RGB_t2HSV_t(RGB, HSV);
}